package com.itfreer.data.input;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.itfreer.data.check.CheckConfigService;
import com.itfreer.data.check.CheckService;
import com.itfreer.data.check.entity.CheckConfigEntity;
import com.itfreer.data.check.entity.CheckHistoryEntity;
import com.itfreer.data.check.imp.DataTypeCheckPara;
import com.itfreer.data.check.imp.DictionaryCheckPara;
import com.itfreer.data.check.imp.MaxlenCheckPara;
import com.itfreer.data.check.imp.NullableCheckPara;
import com.itfreer.data.input.entity.InputConfigEntity;
import com.itfreer.data.input.entity.InputConfigItemEntity;
import com.itfreer.data.utils.ValueConvertUtils;
import com.itfreer.form.api.dictionary.DictionaryEntity;
import com.itfreer.form.api.dictionary.DictionaryService;
import com.itfreer.utils.json.JsonUtils;

/**
 * 数据导入接口
 */
@Component
public class InputServiceImp implements InputService {

	@Autowired
	private InputConfigService inputConfigService;

	@Autowired
	private CheckConfigService checkConfigService;

	@Autowired
	private CheckService checkService;

	@Autowired
	private DictionaryService dictionaryService;

	/**
	 * 数据导入，并进行数据检测
	 * 
	 * @param inputID
	 *            导入配置ID
	 * @param datas
	 *            导入数据
	 * @return
	 * @throws Exception
	 */
	public InputResult inputEx(String inputID, List<Map<String, Object>> datas) throws Exception {
		if (datas == null || datas.size() <= 0) {
			return null;
		}

		// 1.获取配置信息，如果没有配置信息，将不处理导入操作
		InputConfigEntity config = inputConfigService.getEntity(inputID);
		if (config == null) {
			return null;
		}
		Set<InputConfigItemEntity> configs = config.getItems();
		if (configs == null || configs.size() <= 0) {
			return null;
		}

		InputResult inputResult = new InputResult();
		// 2.将输入数据转换为以字段名为key的map中
		List<Map<String, Object>> result = new ArrayList<>();
		String key = null;
		for (Map<String, Object> data : datas) {
			Map<String, Object> item = new HashMap<>();
			for (InputConfigItemEntity c : configs) {
				key = c.getOrder().toString();
				item.put(c.getName(), data.get(key));
			}
			result.add(item);
		}

		// 3.组织检查参数
		List<CheckConfigEntity> checkConfigs = null;
		if (config.getCheckType() == null || config.getCheckType().equals("")) {
			checkConfigs = getDefConfig(configs);
		} else {
			Map<String, Object> where = new HashMap<>();
			where.put("checkType", config.getCheckType());
			Map<String, Integer> ordre = new HashMap<>();
			ordre.put("order", 0);
			checkConfigs = checkConfigService.getEntitys(where, ordre);
		}

		// 4.数据检测
		CheckHistoryEntity checkResult = new CheckHistoryEntity();
		checkResult.setName(config.getName());
		checkResult.setDataid(config.getId());
		checkResult.setType("数据导入");
		checkResult = checkService.check(checkResult, result, checkConfigs, 1);
		if (checkResult.getState() == null || checkResult.getState() == false) {
			inputResult.setSuccess(false);
			inputResult.setLog(checkResult);
			return inputResult;
		}

		// 5.转换数据格式
		for (Map<String, Object> data : result) {
			for (InputConfigItemEntity c : configs) {
				key = c.getName();

				// 字典转换
				if (c.getDictionaryName() != null && !c.getDictionaryName().trim().equals("")
						&& (c.getDicid() == null || c.getDicid() == false)) {
					String textValue = data.get(key).toString().trim();
					List<DictionaryEntity> items = dictionaryService.getAllList(c.getDictionaryName(),null,null);
					for (DictionaryEntity item : items) {
						if (item.getDisplay().equals(textValue)) {
							data.put(key, item.getId());
							break;
						}
					}
				} else {
					data.put(key, ValueConvertUtils.ConvertValue(c.getDataType(), data.get(key)));
				}
			}
		}

		// 6.获取主键
		List<KeyFieldPara> keyFields = new ArrayList<>();
		for (InputConfigItemEntity c : configs) {
			if (c.getKey() != null && c.getKey() == true) {
				KeyFieldPara p = new KeyFieldPara();
				p.setFieldName(c.getName());
				p.setFieldAliasName(c.getAliasName());
				keyFields.add(p);
			}
		}
		inputResult.setSuccess(true);
		inputResult.setInputDatas(result);
		inputResult.setKeyFields(keyFields);
		inputResult.setLog(checkResult);
		inputResult.setRepetitionStrategy(config.getRepetitionStrategy());

		return inputResult;
	}

	/**
	 * 数据导入，并进行数据检测
	 * 
	 * @param inputID
	 *            导入配置ID
	 * @param datas
	 *            导入数据
	 * @return
	 * @throws Exception
	 */
	public List<Map<String, Object>> input(String inputID, List<Map<String, Object>> datas) throws Exception {
		InputResult result = inputEx(inputID, datas);
		if (result == null) {
			return null;
		} else {
			return result.getInputDatas();
		}
	}

	/**
	 * 组织默认检查项
	 * 
	 * @param configs
	 * @return
	 */
	private List<CheckConfigEntity> getDefConfig(Set<InputConfigItemEntity> configs) {
		// 3.数据检测
		List<CheckConfigEntity> checkConfigs = new ArrayList<>();
		// 3.1 数据类型检查
		List<DataTypeCheckPara> dataTypePara = new ArrayList<>();
		for (InputConfigItemEntity c : configs) {
			DataTypeCheckPara item = new DataTypeCheckPara();
			item.setFieldName(c.getName());
			item.setFieldAliasName(c.getAliasName());
			item.setFieldType(c.getDataType());
			dataTypePara.add(item);
		}
		CheckConfigEntity dataTypeCheck = new CheckConfigEntity();
		dataTypeCheck.setType("1");
		dataTypeCheck.setName("数据类型检查");
		dataTypeCheck.setTacheid(1);
		dataTypeCheck.setTachename("基础检查");
		dataTypeCheck.setBeanname("DataTypeCheck");
		dataTypeCheck.setOrder(1);
		dataTypeCheck.setRule("各数据需满足指定数据类型");
		dataTypeCheck.setParas(JsonUtils.toJSONString(dataTypePara));
		checkConfigs.add(dataTypeCheck);

		// 3.2 字典域值检查
		List<DictionaryCheckPara> dicPara = new ArrayList<>();
		List<DictionaryCheckPara> dicTextPara = new ArrayList<>();
		for (InputConfigItemEntity c : configs) {
			if (c.getDictionaryName() != null && !c.getDictionaryName().trim().equals("")) {
				DictionaryCheckPara item = new DictionaryCheckPara();
				item.setFieldName(c.getName());
				item.setFieldAliasName(c.getAliasName());
				item.setFieldDicname(c.getDictionaryName());
				if (c.getDicid() != null && c.getDicid() == true) {
					dicPara.add(item);
				} else {
					dicTextPara.add(item);
				}
			}
		}
		if (dicPara.size() > 0) {
			CheckConfigEntity dicParaCheck = new CheckConfigEntity();
			dicParaCheck.setType("1");
			dicParaCheck.setName("域值检查");
			dicParaCheck.setTacheid(1);
			dicParaCheck.setTachename("基础检查");
			dicParaCheck.setBeanname("DictionaryCheck");
			dicParaCheck.setOrder(2);
			dicParaCheck.setRule("检查给定的值在域值范围内");
			dicParaCheck.setParas(JsonUtils.toJSONString(dicPara));
			checkConfigs.add(dicParaCheck);
		}
		if (dicTextPara.size() > 0) {
			CheckConfigEntity dicTextParaCheck = new CheckConfigEntity();
			dicTextParaCheck.setType("1");
			dicTextParaCheck.setName("域值检查");
			dicTextParaCheck.setTacheid(1);
			dicTextParaCheck.setTachename("基础检查");
			dicTextParaCheck.setBeanname("DictionaryTextCheck");
			dicTextParaCheck.setOrder(3);
			dicTextParaCheck.setRule("检查给定的值在域值范围内");
			dicTextParaCheck.setParas(JsonUtils.toJSONString(dicTextPara));
			checkConfigs.add(dicTextParaCheck);
		}

		// 3.3 长度检查
		List<MaxlenCheckPara> maxlenPara = new ArrayList<>();
		MaxlenCheckPara item = null;
		for (InputConfigItemEntity c : configs) {
			switch (c.getDataType()) {
			case "STRING":
				if (c.getMaxlen() != null) {
					item = new MaxlenCheckPara();
					item.setFieldName(c.getName());
					item.setFieldAliasName(c.getAliasName());
					item.setFieldLen(c.getMaxlen().toString());
					maxlenPara.add(item);
				}
				break;
			case "CHAR":
				item = new MaxlenCheckPara();
				item.setFieldName(c.getName());
				item.setFieldAliasName(c.getAliasName());
				item.setFieldLen("1");
				maxlenPara.add(item);
				break;
			case "DECIMAL":
			case "DOUBLE":
			case "SINGLE":
				if (c.getMaxlen() != null && c.getDecimaldigits() != null) {
					item = new MaxlenCheckPara();
					item.setFieldName(c.getName());
					item.setFieldAliasName(c.getAliasName());
					item.setFieldLen(c.getMaxlen().toString() + "." + c.getDecimaldigits());
					maxlenPara.add(item);
				}
				break;
			case "BOOLEAN":
			case "TEXT":
			case "DATE":
			case "DATETIME":
			case "INT16":
			case "INT":
			case "UINT16":
			case "UINT":
			case "INT64":
			case "UINT64":
			case "BYTEARRAY":
				break;
			default:
				break;
			}
		}
		if (maxlenPara.size() > 0) {
			CheckConfigEntity maxlenTypeCheck = new CheckConfigEntity();
			maxlenTypeCheck.setType("1");
			maxlenTypeCheck.setName("数据长度检查");
			maxlenTypeCheck.setTacheid(1);
			maxlenTypeCheck.setTachename("基础检查");
			maxlenTypeCheck.setBeanname("MaxlenCheck");
			maxlenTypeCheck.setOrder(4);
			maxlenTypeCheck.setRule("各数据需满足指定数据长度");
			maxlenTypeCheck.setParas(JsonUtils.toJSONString(maxlenPara));
			checkConfigs.add(maxlenTypeCheck);
		}

		// 3.4 必填项检查
		List<NullableCheckPara> nullablePara = new ArrayList<>();
		for (InputConfigItemEntity c : configs) {
			if (c.getKey() != null && c.getKey() == true) {
				NullableCheckPara nitem = new NullableCheckPara();
				nitem.setFieldName(c.getName());
				nitem.setFieldAliasName(c.getAliasName());
				nullablePara.add(nitem);
			} else if (c.getAllowNull() == null || c.getAllowNull() == false) {
				NullableCheckPara nitem = new NullableCheckPara();
				nitem.setFieldName(c.getName());
				nitem.setFieldAliasName(c.getAliasName());
				nullablePara.add(nitem);
			}
		}
		if (nullablePara.size() > 0) {
			CheckConfigEntity nullableTypeCheck = new CheckConfigEntity();
			nullableTypeCheck.setType("1");
			nullableTypeCheck.setName("必填项检查");
			nullableTypeCheck.setTacheid(1);
			nullableTypeCheck.setTachename("基础检查");
			nullableTypeCheck.setBeanname("NullableCheck");
			nullableTypeCheck.setOrder(5);
			nullableTypeCheck.setRule("各数据需满足必填检查");
			nullableTypeCheck.setParas(JsonUtils.toJSONString(nullablePara));
			checkConfigs.add(nullableTypeCheck);
		}
		return checkConfigs;
	}
}
